home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / video / xevil-1.000 / xevil-1 / locator.C < prev    next >
C/C++ Source or Header  |  1995-07-10  |  21KB  |  971 lines

  1. // "locator.C"
  2.  
  3. /*    Copyright (C) 1994  Steve Hardt
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 1, or (at your option)
  8.     any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     Steve Hardt 
  20.     hardts@athena.mit.edu hardts@media.mit.edu
  21.     hardts@r4002.3dem.bioch.bcm.tmc.edu
  22.     2043 McClendon
  23.     Houston, TX 77030
  24. */
  25.  
  26. #ifndef NO_PRAGMAS
  27. #pragma implementation "locator.h"
  28. #endif
  29.  
  30.  
  31. // Include Files
  32. #include "utils.h"
  33. #include "coord.h"
  34. #include "id.h"
  35. #include "area.h"
  36. #include "physical.h"
  37. #include "locator.h"
  38.  
  39.  
  40.  
  41. // Defines
  42. #define EXTRA_DRAW_ROWS 1
  43. #define EXTRA_DRAW_COLS 1
  44.  
  45.  
  46.  
  47. // Functions
  48. const Area &OLgridEntry::get_area() 
  49. {
  50.   assert(prev);
  51.   return entry->physical->get_area();
  52. }
  53.  
  54.  
  55.  
  56. int OLgridEntry::get_drawing_level() 
  57. {
  58.   assert(entry->physical && prev); 
  59.   return entry->physical->get_drawing_level();
  60. }
  61.  
  62.  
  63.  
  64. void OLgridEntry::insert(OLgrid grid,const GLoc &gl)
  65. {
  66.   assert((prev == NULL) && (next == NULL));
  67.  
  68.   assert(Locator::valid(gl));
  69.   entry->gloc = gl;
  70.  
  71.   next = grid[gl.vert][gl.horiz]->next;
  72.   prev = grid[gl.vert][gl.horiz];
  73.   if (grid[gl.vert][gl.horiz]->next)
  74.     grid[gl.vert][gl.horiz]->next->prev = this;
  75.   grid[gl.vert][gl.horiz]->next = this;
  76. }
  77.  
  78.  
  79.  
  80. void OLgridEntry::remove()
  81. {
  82.   assert(prev);
  83.  
  84.   if (next)
  85.     next->prev = prev;
  86.   prev->next = next;
  87.   prev = next = NULL;
  88. }
  89.  
  90.  
  91.  
  92. void OLshadowEntry::insert(OLshadows shadows,const GLoc &gl)
  93. {
  94.   assert((prev == NULL) && (next == NULL));
  95.  
  96.   entry->shadowGloc = gl;
  97.   assert(Locator::valid(gl));
  98.  
  99.   next = shadows[gl.vert][gl.horiz]->next;
  100.   prev = shadows[gl.vert][gl.horiz];
  101.   if (shadows[gl.vert][gl.horiz]->next)
  102.     shadows[gl.vert][gl.horiz]->next->prev = this;
  103.   shadows[gl.vert][gl.horiz]->next = this;
  104. }
  105.  
  106.  
  107.  
  108. void OLshadowEntry::remove()
  109. {
  110.   assert (prev);
  111.  
  112.   if (next)
  113.     next->prev = prev;
  114.   prev->next = next;
  115.   prev = next = NULL;
  116. }
  117.  
  118.  
  119.  
  120. HumanP Incarnator::operator () ()
  121. {
  122.   while (n < locator->humansNum && 
  123.      !(locator->reincarnating[n] &&
  124.        locator->reincarnateTimers[n].ready()))
  125.     n++;
  126.  
  127.   if (n == locator->humansNum)
  128.     return NULL;
  129.   else
  130.     {
  131.       // Extract human.
  132.       locator->reincarnating[n] = False;
  133.       return locator->humans[n];
  134.     }
  135. }
  136.  
  137.  
  138.  
  139. PhysicalP PhysicalIter::operator () ()
  140. {
  141.   while (n < locator->listMax && !locator->list[n].valid)
  142.     n++;
  143.   
  144.   assert(n <= locator->listMax);
  145.   if (n == locator->listMax)
  146.     return NULL;
  147.   else
  148.     {
  149.       n++;
  150.       return locator->list[n-1].physical;
  151.     }
  152. }
  153.  
  154.  
  155.  
  156. Locator::Locator(WorldP w)
  157. {
  158.   world  = w;
  159.  
  160.   uniqueGen = 0;
  161.  
  162.   listMax = 0;
  163.  
  164.   for (int c = 0; c < OL_GRID_HORIZ_MAX; c++)
  165.     for (int r = 0; r < OL_GRID_VERT_MAX; r++)
  166.       {
  167.     grid[r][c] = new OLgridEntry(NULL);
  168.     assert(grid[r][c]);
  169.     shadows[r][c] = new OLshadowEntry();
  170.     assert(shadows[r][c]);
  171.       }
  172.  
  173.   addNum = 0;
  174.   shadowDelNum = 0;
  175.  
  176.   xValid = False;
  177.  
  178.   head = tail = 0;
  179.   messagesIgnore = False;
  180.  
  181.   humansNum = enemiesNum = neutralsNum = 0;
  182.   for (int n = 0; n < HUMANS_MAX; n++)
  183.     {
  184.       Timer nTimer(REINCARNATE_TIME);
  185.       reincarnateTimers[n] = nTimer;
  186.     }
  187. }
  188.  
  189.  
  190.  
  191. void Locator::add(PhysicalP p)
  192. {
  193.   if (addNum >= OL_LIST_MAX)
  194.     {
  195.       cerr << "Object locator is full.  Can only have " << OL_LIST_MAX 
  196.        << " objects in the game." << endl;
  197.       assert(0);
  198.     }
  199.   addList[addNum] = p;
  200.   addNum++;
  201.   p->set_id(reserve_list_entry(p));
  202. }
  203.  
  204.  
  205.  
  206. void Locator::get_nearby(PhysicalP nearby[OL_NEARBY_MAX],int &nitems,
  207.              PhysicalP p,int radius)
  208. {
  209.   int glocRadius = (int)ceil(radius / OL_GRID_SIZE_MAX);
  210.   int radius_2 = radius * radius;
  211.   nitems = 0;
  212.  
  213.   const Id id = p->get_id();
  214.   GLoc pGLoc = list[id.index].gloc;
  215.   const Area &pArea = p->get_area();
  216.   Pos pPos = pArea.get_middle();
  217.  
  218.   GLoc gloc;
  219.   for (gloc.horiz = pGLoc.horiz - glocRadius; 
  220.        gloc.horiz <= pGLoc.horiz + glocRadius; gloc.horiz++)
  221.     for (gloc.vert = pGLoc.vert - glocRadius; 
  222.      gloc.vert <= pGLoc.vert + glocRadius; 
  223.      gloc.vert++)
  224.       if (valid(gloc))
  225.     {
  226.       // Skip the header.
  227.       OLgridEntry *ge = grid[gloc.vert][gloc.horiz]->get_next(); 
  228.       while (ge)
  229.         {
  230.           PhysicalP p2 = ge->get_physical();
  231.           if (p != p2)
  232.         {
  233.           const Area& area = p2->get_area();
  234.           if (pPos.distance_2(area.get_middle()) <= radius_2)
  235.             {
  236.               assert(nitems < OL_NEARBY_MAX);
  237.               nearby[nitems] = p2;
  238.               nitems++;
  239.             }
  240.         }
  241.           ge = ge->get_next();
  242.         }
  243.     }
  244. }
  245.  
  246.  
  247.  
  248. OLsig Locator::lookup(PhysicalP &p, const Id &id)
  249. {
  250.   p = lookup(id);
  251.   return p ? OL_NO_SIG : OL_NOT_FOUND;
  252. }
  253.  
  254.  
  255.  
  256. PhysicalP Locator::lookup(const Id &id)
  257. {
  258.   if ((id.index != Id::INVALID) &&
  259.       (list[id.index].valid || list[id.index].reserved))
  260.     {
  261.       Id testId = list[id.index].physical->get_id();
  262.       if (testId == id)
  263.     return list[id.index].physical;
  264.     }
  265.   return NULL;
  266. }
  267.  
  268.  
  269.  
  270. IntelP Locator::lookup(const IntelId &iId)
  271. {
  272.   if (iId.index == IntelId::INVALID)
  273.     return NULL;
  274.  
  275.   // Check humans.
  276.   if (iId.index < humansNum)
  277.     {
  278.       IntelId testId = humans[iId.index]->get_intel_id();
  279.       if (testId == iId)
  280.     return humans[iId.index];
  281.     }
  282.  
  283.   // Check enemies.
  284.   if (iId.index < enemiesNum && enemies[iId.index]->alive())
  285.     {
  286.       IntelId testId = enemies[iId.index]->get_intel_id();
  287.       if (testId == iId)
  288.     return enemies[iId.index];
  289.     }
  290.  
  291.   // Check neutrals.
  292.   if (iId.index < neutralsNum && neutrals[iId.index]->alive())
  293.     {
  294.       IntelId testId = neutrals[iId.index]->get_intel_id();
  295.       if (testId == iId)
  296.     return neutrals[iId.index];
  297.     }
  298.  
  299.   return NULL;
  300. }
  301.  
  302.  
  303.  
  304. void Locator::draw(Drawable window,Xvars &xvars,int dpyNum,const Box &room)
  305. {
  306.   /* Don't draw if outside the world. */
  307.   if (world->overlap(room)) 
  308.     {
  309.       if (!xValid)
  310.     init_x(xvars);
  311.       
  312.       // Draw new stuff
  313.       GLoc gridStart; 
  314.       gridStart.horiz = 
  315.     (int)floor((float)room.loc.c / (float)OL_GRID_COL_MAX) - 1;
  316.       gridStart.vert = 
  317.     (int)floor((float)room.loc.r / (float)OL_GRID_ROW_MAX) - 1;
  318.       
  319.       GLoc gridFinish; 
  320.       gridFinish.horiz = (int)ceil((float)(room.loc.c + room.dim.colMax) / 
  321.                    (float) OL_GRID_COL_MAX) + 1;
  322.       gridFinish.vert = (int)ceil((float)(room.loc.r + room.dim.rowMax) /
  323.                   (float) OL_GRID_ROW_MAX) + 1;
  324.       
  325.       // Go through all shadows in room.
  326.     GLoc gloc;
  327.       for (gloc.vert = gridStart.vert; gloc.vert < gridFinish.vert; 
  328.        gloc.vert++)
  329.     for (gloc.horiz = gridStart.horiz; gloc.horiz < gridFinish.horiz; 
  330.          gloc.horiz++)
  331.       if (valid(gloc))
  332.         {
  333.           OLshadowEntry *se = shadows[gloc.vert][gloc.horiz]->get_next();
  334.           
  335.           while (se)
  336.         {
  337.           const Area &shadowArea = se->get_area();
  338.           if (se->get_orphaned())
  339.             draw_area(window,xvars,dpyNum,room,shadowArea,gloc);
  340.           else
  341.             {
  342.               OLgridEntry *ge = se->get_grid_entry();
  343.               if (shadowArea.overlap(ge->get_area()))
  344.             se->set_draw_self(False);
  345.               else
  346.             {
  347.               se->set_draw_self(True);
  348.               draw_area(window,xvars,dpyNum,room,
  349.                     shadowArea,gloc);
  350.             }
  351.             }
  352.           se = se->get_next();
  353.         }
  354.         }
  355.       
  356.       // go through all grid entries in room.
  357.       for (gloc.vert = gridStart.vert; gloc.vert < gridFinish.vert; 
  358.        gloc.vert++)
  359.     for (gloc.horiz = gridStart.horiz; gloc.horiz < gridFinish.horiz; 
  360.          gloc.horiz++)
  361.       if (valid(gloc))
  362.         {
  363.           OLgridEntry *ge = grid[gloc.vert][gloc.horiz]->get_next();
  364.           
  365.           while (ge)
  366.         {
  367.           OLentry *ent = ge->get_entry();
  368.           assert (ent->gloc == gloc);
  369.  
  370.           if (ge->get_mapped() || ge->get_flash())
  371.             {
  372.               OLshadowEntry *se = ge->get_shadow_entry();
  373.               
  374.               if (se->draw_self())
  375.             draw_area(window,xvars,dpyNum,room,ge->get_area(),
  376.                   gloc);
  377.               else
  378.             {
  379.               const Area &shadowArea = se->get_area();
  380.               draw_area(window,xvars,dpyNum,room,
  381.                     shadowArea.combine(ge->get_area()),gloc);
  382.             }
  383.             }
  384.           ge = ge->get_next();
  385.         }
  386.         }
  387.     }
  388. }
  389.  
  390.   
  391.  
  392. void Locator::reset()
  393. {
  394.   // Destroy the addList.
  395.   for (int n = 0; n < addNum; n++)
  396.     delete addList[n];
  397.   addNum = 0;
  398.  
  399.   for (n = 0; n < listMax; n++)
  400.     if (list[n].valid)
  401.       {
  402.     del_now(list[n].physical);
  403.     delete list[n].physical;
  404.       }
  405.   listMax = 0;
  406.  
  407.   uniqueGen = 0;
  408.   
  409.   // Check grid integrity.  There should only be the headers remaining.
  410.   for (int c = 0; c < OL_GRID_HORIZ_MAX; c++)
  411.     for (int r = 0; r < OL_GRID_VERT_MAX; r++)
  412.       assert( grid[r][c] && (grid[r][c]->get_next() == NULL));
  413.  
  414.   // Delete all messages remaining in the queue.
  415.   while (head != tail)
  416.     {
  417.       delete messages[head];
  418.       head = (head + 1) % OL_MESSAGES_MAX;
  419.     }
  420.  
  421.   for (n = 0; n < humansNum; n++)
  422.     delete humans[n];
  423.  
  424.   for (n = 0; n < enemiesNum; n++)
  425.     delete enemies[n];
  426.  
  427.   for (n = 0; n < neutralsNum; n++)
  428.     delete neutrals[n];
  429.  
  430.   humansNum = enemiesNum = neutralsNum = 0;
  431. }
  432.  
  433.  
  434.  
  435. void Locator::clock()
  436. {
  437.   // Kill shadow delete list.
  438.   for (int n = 0; n < shadowDelNum; n++)
  439.     {
  440.       shadowDelList[n]->remove();
  441.       delete shadowDelList[n];
  442.     }
  443.   shadowDelNum = 0;
  444.  
  445.   // Move shadows to previous area.
  446.   for (n = 0; n < listMax; n++)
  447.     if (list[n].valid && (list[n].mapped || list[n].flash))
  448.       {
  449.     list[n].shadowEntry->set_area(list[n].physical->get_area());
  450.     GLoc realGloc = compute_gloc(list[n].shadowEntry->get_area());
  451.  
  452.     if (list[n].shadowGloc != realGloc)
  453.       {
  454.         list[n].shadowEntry->remove();
  455.         list[n].shadowEntry->insert(shadows,realGloc);
  456.       }
  457.       }
  458.  
  459.   /* Collision phase.  Physical::collide will be called at most once for any
  460.      object. */
  461.   collision_checks();
  462.  
  463.   /* Intelligence phase and action phase.  Set next variables.  Externally 
  464.      visible state should not change. 
  465.      Exceptions to this: canTake. */
  466.   for (n = 0; n < listMax; n++)
  467.     if (list[n].valid)
  468.       {
  469.     // Think before you act.
  470.     list[n].physical->intelligence();
  471.     list[n].physical->act();
  472.       }
  473.  
  474.   /* Kill objects outside world. */
  475.   for (n = 0; n < listMax; n++)
  476.     if (list[n].valid && (list[n].mapped || list[n].flash))
  477.       {
  478.     const Area &area = list[n].physical->get_area_next();
  479.     if (!world->inside(area.middle_wsquare()))
  480.       //        (&& !list[n].physical->delete_me())
  481.       {
  482.         list[n].physical->set_quiet_death();
  483.         list[n].physical->kill_self();
  484.  
  485. #ifdef PRINT_ERRORS
  486.         cerr << list[n].physical->identify() << 
  487.           " knocked out of world." << endl; 
  488. #endif
  489.       }
  490.       }
  491.   
  492.   // Check for death.  I.e. healthNext < 0.
  493.   /* NOTE: If using kill_self in this phase, an object must manually 
  494.      call die and check for die_called().  Hack in Frog::die. */
  495.   for (n = 0; n < listMax; n++)
  496.     if (list[n].valid &&
  497.     list[n].physical->get_health_next() < 0 && 
  498.     list[n].physical->get_health() >= 0 &&
  499.     !list[n].physical->die_called())
  500.       list[n].physical->die();
  501.   
  502.   // Update externally visable state.
  503.   for (n = 0; n < listMax; n++)
  504.     if (list[n].valid) 
  505.       list[n].physical->update();
  506.   
  507.   /* Update the locator grid, shifting gridEntries around if necessary. */
  508.   for (n = 0; n < listMax; n++)
  509.     if (list[n].valid)
  510.       {
  511.     allign_flash_and_mapped(n);
  512.     if (list[n].mapped || list[n].flash)
  513.       {
  514.         const Area &area = list[n].physical->get_area();
  515.         if (world->inside(area.middle_wsquare()))
  516.           {
  517.         GLoc realGLoc = compute_gloc(list[n].physical);
  518.         
  519.         if (list[n].gloc != realGLoc)
  520.           {
  521.             list[n].gridEntry->remove();
  522.             list[n].gridEntry->insert(grid,realGLoc);
  523.           }
  524.           }
  525.         else
  526.           assert(list[n].physical->die_called() && 
  527.              list[n].physical->delete_me());
  528.       }
  529.  
  530.     list[n].collided = False;
  531.       }
  532.  
  533.   // Add all objects on the list.
  534.   for (n = 0; n < addNum; n++)
  535.     add_now(addList[n]);
  536.   addNum = 0;
  537.  
  538.   // Delete objects that are dead.
  539.   for (n = 0; n < listMax; n++)
  540.     if (list[n].valid && list[n].physical->delete_me())
  541.       {
  542.     del_now(list[n].physical);
  543.     delete list[n].physical;
  544.       }
  545.   
  546.   reincarnate_clock();
  547. }
  548.  
  549.  
  550.  
  551. void Locator::message_enq(char *msg)
  552. {
  553.   if (messagesIgnore)
  554.     {
  555.       delete msg;
  556.       return;
  557.     }
  558.  
  559.   if ((tail + 1) % OL_MESSAGES_MAX != head)
  560.     {
  561.       messages[tail] = msg;
  562.       tail = (tail + 1) % OL_MESSAGES_MAX;
  563.     }
  564.   else
  565.     {
  566.       delete msg;
  567. //    cout << "Warning: Message queue overflow.  Discarding message." << endl;
  568.     }
  569. }
  570.  
  571.  
  572.  
  573. char *Locator::message_deq()
  574. {
  575.   if (head == tail)
  576.     return NULL;
  577.  
  578.   int ret = head;
  579.   head = (head + 1) % OL_MESSAGES_MAX;
  580.   
  581.   return messages[ret];
  582. }
  583.  
  584.  
  585.  
  586. void Locator::register_human(HumanP h)
  587. {
  588.   // Assign h an IntelId.
  589.   assert(humansNum < HUMANS_MAX);
  590.   IntelId iId = h->get_intel_id();
  591.   assert(iId.index == IntelId::INVALID);
  592.   iId.index = humansNum;
  593.   iId.unique = uniqueGen;
  594.   uniqueGen++;
  595.   h->set_intel_id(iId);
  596.  
  597.   // Add to the array of Humans.
  598.   humans[humansNum] = h;
  599.   reincarnating[humansNum] = False;
  600.   reincarnateTimers[humansNum].reset();
  601.   humansNum++;
  602. }
  603.  
  604.  
  605.  
  606. void Locator::register_enemy(EnemyP m)
  607. {
  608.   IntelId iId = m->get_intel_id();
  609.   assert(iId.index == IntelId::INVALID);
  610.   iId.unique = uniqueGen;
  611.   uniqueGen++;
  612.  
  613.   // Try inserting in current array.
  614.   for (int n = 0; n < enemiesNum; n++)
  615.     if (!enemies[n]->alive())
  616.       {
  617.     delete enemies[n];
  618.     enemies[n] = m;
  619.     iId.index = n;
  620.     m->set_intel_id(iId);
  621.     return;
  622.       }
  623.  
  624.   // Else add to array.
  625.   assert(enemiesNum < ENEMIES_MAX);
  626.   enemies[enemiesNum] = m;
  627.   iId.index = enemiesNum;
  628.   m->set_intel_id(iId);
  629.   enemiesNum++;
  630. }
  631.  
  632.  
  633.  
  634. void Locator::register_neutral(NeutralP m)
  635. {
  636.   IntelId iId = m->get_intel_id();
  637.   assert(iId.index == IntelId::INVALID);
  638.   iId.unique = uniqueGen;
  639.   uniqueGen++;
  640.  
  641.   // Try inserting in current array.
  642.   for (int n = 0; n < neutralsNum; n++)
  643.     if (!neutrals[n]->alive())
  644.       {
  645.     delete neutrals[n];
  646.     neutrals[n] = m;
  647.     iId.index = n;
  648.     m->set_intel_id(iId);
  649.     return;
  650.       }
  651.  
  652.   // Else add to array.
  653.   assert(neutralsNum < NEUTRALS_MAX);
  654.   neutrals[neutralsNum] = m;
  655.   iId.index = neutralsNum;
  656.   m->set_intel_id(iId);
  657.   neutralsNum++;
  658. }
  659.  
  660.  
  661.  
  662. int Locator::humans_playing()
  663. {
  664.   for (int n = 0, ret = 0; n < humansNum; n++)
  665.     if (humans[n]->alive() || humans[n]->reincarnate_me())
  666.       ret++;
  667.   return ret;
  668. }
  669.  
  670.  
  671.  
  672. int Locator::enemies_alive()
  673. {
  674.   for (int n = 0, ret = 0; n < enemiesNum; n++)
  675.     if (enemies[n]->alive())
  676.       ret++;
  677.   return ret;
  678. }
  679.  
  680.  
  681.  
  682. int Locator::neutrals_alive()
  683. {
  684.   for (int n = 0, ret = 0; n < neutralsNum; n++)
  685.     if (neutrals[n]->alive())
  686.       ret++;
  687.   return ret;
  688. }
  689.  
  690.  
  691.  
  692. void Locator::add_now(PhysicalP p)
  693. {
  694.   Id id = p->get_id();
  695.   int n = id.index;
  696.  
  697.   assert (list[n].physical == p);
  698.   list[n].valid = True;
  699.   list[n].collided = False;
  700.   list[n].collidable = p->collidable();
  701.   list[n].mapped = p->get_mapped();
  702.   list[n].flash = p->get_flash();
  703.  
  704.   if (list[n].mapped || list[n].flash)
  705.     {
  706.       // Create and add shadow and grid entries.
  707.       list[n].gridEntry = new OLgridEntry(&list[n]);
  708.       assert(list[n].gridEntry);
  709.       list[n].shadowEntry = new OLshadowEntry(p->get_area(),&list[n]);
  710.       assert(list[n].shadowEntry);
  711.       GLoc gloc = compute_gloc(list[n].physical);
  712.       list[n].gridEntry->insert(grid,gloc);
  713.       list[n].shadowEntry->insert(shadows,gloc);
  714.     }
  715. }
  716.  
  717.  
  718.  
  719. void Locator::del_now(PhysicalP p)
  720. {
  721.   Id id = p->get_id();
  722.   list[id.index].valid = False;
  723.   list[id.index].reserved = False;
  724.  
  725.   if (list[id.index].mapped || list[id.index].flash)
  726.     {
  727.       list[id.index].gridEntry->remove();
  728.       delete list[id.index].gridEntry;
  729.  
  730.       shadowDelList[shadowDelNum] = list[id.index].shadowEntry;
  731.       list[id.index].shadowEntry->set_orphaned();
  732.       shadowDelNum++;
  733.     }
  734.  
  735.   // Decrease effective size of list.
  736.   if (id.index == listMax - 1)
  737.     listMax--;
  738. }
  739.  
  740.  
  741.  
  742. void Locator::allign_flash_and_mapped(int n)
  743. {
  744.   Boolean flash = list[n].physical->get_flash();
  745.   Boolean mapped = list[n].physical->get_mapped();
  746.  
  747.   // Add new OLgridEntry and shadowEntry.
  748.   if (!(list[n].mapped || list[n].flash) && (mapped || flash))
  749.     {
  750.       list[n].gridEntry = new OLgridEntry(&list[n]);
  751.       assert(list[n].gridEntry);
  752.       list[n].shadowEntry = 
  753.     new OLshadowEntry(list[n].physical->get_area(),&list[n]);
  754.       assert(list[n].shadowEntry);
  755.       GLoc gloc = compute_gloc(list[n].physical);
  756.       list[n].gridEntry->insert(grid,gloc);      
  757.       list[n].shadowEntry->insert(shadows,gloc);
  758.     }
  759.  
  760.   // Destroy grid entry and mark shadow entry for deletion.
  761.   if ((list[n].mapped || list[n].flash) && !(mapped || flash))
  762.     {
  763.       list[n].gridEntry->remove();
  764.       delete list[n].gridEntry;
  765.       shadowDelList[shadowDelNum] = list[n].shadowEntry;
  766.       list[n].shadowEntry->set_orphaned();
  767.       shadowDelNum++;
  768.     }
  769.   
  770.   list[n].mapped = mapped;
  771.   list[n].flash = flash;
  772. }
  773.  
  774.  
  775.  
  776. void Locator::init_x(Xvars &xvars)
  777. {
  778.   assert(xValid == False);
  779.  
  780.   for (int dpyNum = 0; dpyNum < xvars.dpyMax; dpyNum++)
  781.     {
  782.       xdata.buffer[dpyNum] = 
  783.     XCreatePixmap(xvars.dpy[dpyNum],xvars.root[dpyNum],
  784.               (OL_GRID_COL_MAX + 2 * EXTRA_DRAW_COLS) 
  785.               * WSQUARE_WIDTH,
  786.               (OL_GRID_ROW_MAX + 2 * EXTRA_DRAW_ROWS) 
  787.               * WSQUARE_HEIGHT,
  788.               xvars.depth[dpyNum]);
  789.   
  790.       Size roomSize = world->get_room_size();
  791.       xdata.roomBuffer[dpyNum] = 
  792.     XCreatePixmap(xvars.dpy[dpyNum],xvars.root[dpyNum],
  793.               roomSize.width,roomSize.height,
  794.               xvars.depth[dpyNum]);
  795.     }
  796.   xValid = True;
  797. }
  798.  
  799.  
  800.  
  801. Id Locator::reserve_list_entry(PhysicalP p)
  802. {
  803.   Id dummy;
  804.   assert(p->get_id(dummy) == PH_NOT_SET);
  805.  
  806.   for (int n = 0; ; n++)
  807.     {
  808.       assert(n <= listMax); 
  809.  
  810.       // Increase effective size of list.
  811.       if (n == listMax)
  812.     {
  813.       assert(n < OL_LIST_MAX); // Object locator list is full.
  814.       list[n].valid = False;
  815.       list[n].reserved = False;
  816.       listMax++;
  817.     }
  818.  
  819.       if (!list[n].valid && !list[n].reserved)
  820.     {
  821.       Id ret;
  822.       ret.index = n;
  823.       ret.unique = uniqueGen;
  824.       uniqueGen++;
  825.       list[n].reserved = True;
  826.       list[n].physical = p;
  827.       return ret;
  828.     }
  829.     }
  830. }
  831.  
  832.  
  833.  
  834. void Locator::collision_checks()
  835. {
  836.   for (int n = 0; n < listMax; n++)
  837.     if (list[n].valid && !list[n].collided && list[n].mapped && 
  838.     list[n].collidable)
  839.       {
  840.     PhysicalP p1 = list[n].physical;
  841.     GLoc gloc;
  842.  
  843.     for (gloc.vert = list[n].gloc.vert - 1; 
  844.          gloc.vert <= list[n].gloc.vert + 1; 
  845.          gloc.vert++)
  846.       for (gloc.horiz = list[n].gloc.horiz - 1; 
  847.            gloc.horiz <= list[n].gloc.horiz + 1; 
  848.            gloc.horiz++)
  849.         if (valid(gloc))
  850.           {
  851.         // Skip the header.
  852.         OLgridEntry *ge = grid[gloc.vert][gloc.horiz]->get_next(); 
  853.         while (ge)
  854.           {
  855.             PhysicalP p2 = ge->get_physical(); 
  856.             if ((! ge->get_collided()) &&
  857.             ge->get_mapped() &&
  858.             ge->get_collidable() &&
  859.             (p1 != p2) &&
  860.             (p2->get_dont_collide() != p1) &&
  861.             (p1->get_dont_collide() != p2))
  862.               {
  863.             const Area &a1 = p1->get_area();
  864.             if (a1.overlap(p2->get_area()))
  865.               {
  866.                 if (p1->get_mass() > p2->get_mass())
  867.                   p2->avoid(p1);
  868.                 else if (p2->get_mass() > p1->get_mass())
  869.                   p1->avoid(p2);
  870.                 else if (Utils::coinFlip())
  871.                   p1->avoid(p2);
  872.                 else
  873.                   p2->avoid(p1);
  874.                 
  875.                 p1->collide(p2);
  876.                 p2->collide(p1);
  877.                 list[n].collided = True;
  878.                 ge->set_collided(True);
  879.               }
  880.               }
  881.             ge = ge->get_next();
  882.           }
  883.           }
  884.       }
  885. }
  886.  
  887.  
  888.  
  889. GLoc Locator::compute_gloc(PhysicalP p)
  890. {
  891.   const Area &area = p->get_area();
  892.   Pos middle = area.get_middle(); 
  893.   GLoc gloc;
  894.   gloc.horiz = middle.x / OL_GRID_WIDTH;
  895.   gloc.vert = middle.y / OL_GRID_HEIGHT;
  896.   return gloc;
  897. }
  898.  
  899.  
  900.  
  901. GLoc Locator::compute_gloc(const Area &area)
  902. {
  903.   Pos middle = area.get_middle(); 
  904.   GLoc gloc;
  905.   gloc.horiz = middle.x / OL_GRID_WIDTH;
  906.   gloc.vert = middle.y / OL_GRID_HEIGHT;
  907.   return gloc;
  908. }
  909.  
  910.  
  911.  
  912. void Locator::draw_area(Drawable window,Xvars &xvars,int dpyNum,
  913.             const Box &room,const Area &area,const GLoc &gloc)
  914. {
  915.   world->draw(xdata.buffer[dpyNum],xvars,dpyNum,area);
  916.  
  917.   for (int dLevel = 0; dLevel < DRAWING_LEVELS; dLevel++)
  918.     {
  919.       GLoc check;
  920.       for (check.horiz = gloc.horiz - 1; 
  921.        check.horiz <= gloc.horiz + 1; 
  922.        check.horiz++)
  923.     for (check.vert = gloc.vert - 1; 
  924.          check.vert <= gloc.vert + 1; 
  925.          check.vert++)
  926.       if (valid(check))
  927.         {
  928.           OLgridEntry *checkGe = 
  929.         grid[check.vert][check.horiz]->get_next(); 
  930.           
  931.           while (checkGe)
  932.         {
  933.           if ((checkGe->get_drawing_level() == dLevel) && 
  934.               (checkGe->get_flash() || checkGe->get_mapped()))
  935.             {
  936.               PhysicalP checkP = checkGe->get_physical();
  937.               const Area &checkArea = checkP->get_area();
  938.               
  939.               if (checkArea.overlap(area))
  940.             checkP->draw(xdata.buffer[dpyNum],xvars,dpyNum,area);
  941.             }                
  942.           checkGe = checkGe->get_next();
  943.         }
  944.         }
  945.     }
  946.  
  947.   Pos pos;
  948.   Size size;
  949.   area.get_rect(pos,size);
  950.  
  951.   XCopyArea(xvars.dpy[dpyNum],xdata.buffer[dpyNum],window,xvars.gc[dpyNum],
  952.         0,0,size.width,size.height,
  953.         pos.x - room.loc.c * WSQUARE_WIDTH,
  954.         pos.y - room.loc.r * WSQUARE_HEIGHT);
  955. }
  956.  
  957.  
  958.  
  959. void Locator::reincarnate_clock()
  960. {
  961.   for (int n = 0; n < humansNum; n++)
  962.     {
  963.       if (!reincarnating[n] && humans[n]->reincarnate_me())
  964.     {
  965.       reincarnating[n] = True;
  966.       reincarnateTimers[n].set();
  967.     }
  968.       reincarnateTimers[n].clock();
  969.     }
  970. }
  971.